package visitorpattern;


import graph.AdministratorOfAllStartingNodes;
import graph.BookReviewEdge;
import graph.BookReviewGraphInterface;
import graph.BookReviewNode;
import graph.FacadeToObtainGraph;

import java.util.LinkedList;

import bookworm.Book;
import bookworm.BooksAndRatingOfOneAuthor;
import bookworm.Review;

/**
 * class will will also visit already created graph(by the facade)
 * using the visitors it creates
 *
 *
 */
public class CreatesVisitorsAndVisitsGraph 
{
	
	private Visitor visitBookReviews;
	private BookReviewGraphInterface graph; 
	//this class will not use the graph, it'll just initialize it.
	
	public CreatesVisitorsAndVisitsGraph()
	{
		FacadeToObtainGraph graphAdministrator = FacadeToObtainGraph.getInstance();
		this.graph = graphAdministrator.getGraph();
	}
	
	
	public BooksAndRatingOfOneAuthor 
				getBooksAndAverageRatingOfSpecificAuthorBasedOnTag(String authorName, String tag)
	{
		this.visitBookReviews = new BooksFromSpecificAuthorVisitor(authorName, tag);
		AdministratorOfAllStartingNodes knowsAllStartingNodes = 
				AdministratorOfAllStartingNodes.getAdministratorOfAllStartingNodes();
		BookReviewNode startingNodeFromAuthor = 
				knowsAllStartingNodes.getStartingNodeForAuthor(authorName);
		
		if(startingNodeFromAuthor == null)
		{
			//no book from specified author was found
			return null;
		}
		
		//first, we'll visit the starting node. 
		startingNodeFromAuthor.accept(this.visitBookReviews);
		LinkedList<BookReviewEdge> edgesOfStartingNode =
										startingNodeFromAuthor.getIncidentEdges();
		for(int i = 0; i < edgesOfStartingNode.size(); i++)
		{
			//we'll visit the neighbor nodes
			LinkedList<BookReviewNode> startingNodeNeighbors =
											startingNodeFromAuthor.getNeighborsOfNode();
			for(int j = 0; j < startingNodeNeighbors.size(); j++)
			{
				BookReviewNode startingNodeNeighbor = startingNodeNeighbors.get(j);
				startingNodeNeighbor.accept(this.visitBookReviews);
			}
		}
		
		BooksFromSpecificAuthorVisitor visitBooksFromAuthor =
									(BooksFromSpecificAuthorVisitor) visitBookReviews;
		LinkedList<Book> booksFromSpecificAuthor = visitBooksFromAuthor.getBooksFromAuthor();
		LinkedList<Book> booksFromSpecificAuthorAndTag =
									visitBooksFromAuthor.getBooksFromAuthorAndSpecificTag();
		int averageRatingOfAuthor =
				visitBooksFromAuthor.getAverageRatingOfAuthorBasedOnSpecificTag();
		BooksAndRatingOfOneAuthor booksAndAverageRating =
				new BooksAndRatingOfOneAuthor(booksFromSpecificAuthor,
										averageRatingOfAuthor, tag, authorName, booksFromSpecificAuthorAndTag);
		return booksAndAverageRating;
	}
	
	public BooksAndRatingOfOneAuthor getBooksAndAverageRatingOfSpecificAuthor(String authorName)
	{
		return this.getBooksAndAverageRatingOfSpecificAuthorBasedOnTag(authorName, " ");
	}
	
	public LinkedList<Book> getBooksFromSpecificTag(String tag)
	{
		this.visitBookReviews = new BooksFromSpecificTagVisitor(tag);
		AdministratorOfAllStartingNodes knowsAllStartingNodes = 
				AdministratorOfAllStartingNodes.getAdministratorOfAllStartingNodes();
		BookReviewNode startingNodeFromTag = 
				knowsAllStartingNodes.getStartingNodeForTag(tag);
		if(startingNodeFromTag == null)
		{
			//no book from specified tag was found
			return null;
		}
		
		//first, we'll visit the starting node. 
		startingNodeFromTag.accept(this.visitBookReviews);
		LinkedList<BookReviewEdge> edgesOfStartingNode =
												startingNodeFromTag.getIncidentEdges();
		for(int i = 0; i < edgesOfStartingNode.size(); i++)
		{
			//we'll visit the neighbor nodes
			LinkedList<BookReviewNode> startingNodeNeighbors =
													startingNodeFromTag.getNeighborsOfNode();
			for(int j = 0; j < startingNodeNeighbors.size(); j++)
			{
				BookReviewNode startingNodeNeighbor = startingNodeNeighbors.get(j);
				startingNodeNeighbor.accept(this.visitBookReviews);
			}
		}
				
		BooksFromSpecificTagVisitor visitBooksFromTag =
										(BooksFromSpecificTagVisitor) visitBookReviews;
		LinkedList<Book> booksFromSpecificTag = visitBooksFromTag.getBooksFromTag();
		
		return booksFromSpecificTag;
	}
	
	
	

}
